"""
Grave! Important! Важно!

Proletoj el ĉiuj landoj, unuiĝu!
Workers of the world, unite!
Пролетарии всех стран, соединяйтесь!

https://tkom.pro
"""

import sys
import random
import string
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import Permission
from django.db.models import Max, Q

from siriuso.models.postgres import CallableEncoder
from siriuso.utils import default_lingvo, get_enhavo, perms
from universo_bazo.models import UniversoBazaMaks, UniversoBazaRealeco, Realeco
from organizoj.models import Organizo, OrganizoMembro
from main.models import SiriusoBazaAbstrakta3, Uzanto
from kombatantoj.models import Kombatanto
from objektoj.models import ObjektoTemperaturaReghimo, ObjektoTipoKontenero, ObjektoTipoPakumo
from informiloj.models import InformilojUrboj
from mono.models import MonoValuto


# константы/переменные для документов экспедирования
dokumento_Speco_1c = 4 # документы, находящиеся на синхронизации с 1с


# Генерация случайного названия и переименование загружаемых файлов
def datumoj_dosiero(instance, filename):
    if filename:
        return 'dokumentoj/dosiero/{}'.format(filename)
    else:
        letters = string.ascii_letters + string.digits
        rnd_string = ''.join(random.choice(letters) for i in range(10))
    # указание папки для хранения файлов и собирание конечного названия с сохранением изначального расширения
    return 'dokumentoj/dosiero/{0}.{1}'.format(rnd_string, filename.split('.')[-1])


# Сохранённые файлы (dosiero)
class DokumentoDosiero(SiriusoBazaAbstrakta3):

    # Название (ИмяФайла)
    nomo = models.JSONField(verbose_name=_('Nomo'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # Вид печатной формы (ВидПФ)
    formo = models.JSONField(verbose_name=_('Formo'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # Состояние (статус)
    statuso = models.JSONField(verbose_name=_('Statuso'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # присоединенный файл
    dosiero = models.FileField('Dosiero', upload_to=datumoj_dosiero, blank=True)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_dosiero'
        # читабельное название модели, в единственном числе
        verbose_name = _('Dokumento de dosiero')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Dokumentoj de dosiero')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_dosiero', _('Povas vidi dokumentoj de dosiero')),
            ('povas_krei_dokumentoj_dosiero', _('Povas krei dokumentoj de dosiero')),
            ('povas_forigi_dokumentoj_dosiero', _('Povas forigi dokumentoj de dosiero')),
            ('povas_shangxi_dokumentoj_dosiero', _('Povas ŝanĝi dokumentoj de dosiero')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        return '{}: {}'.format(get_enhavo(self.formo, empty_values=True)[0], get_enhavo(self.nomo, empty_values=True)[0])

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_dosiero', 
                'dokumentoj.povas_krei_dokumentoj_dosiero',
                'dokumentoj.povas_forigi_dokumentoj_dosiero',
                'dokumentoj.povas_shangxi_dokumentoj_dosiero'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_dosiero')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_dosiero')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_dosiero'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Категории документов, использует абстрактный класс UniversoBazaMaks
class DokumentoKategorio(UniversoBazaMaks):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность или для которого создана сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # параллельный мир в котором есть эта сущность, может быть в нескольких
    realeco = models.ManyToManyField(Realeco, verbose_name=_('Realeco'),
                                     db_table='dokumentoj_dokumento_kategorioj_realeco_ligiloj')

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_kategorioj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Kategorio de dokumentoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Kategorioj de dokumentoj')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_kategorioj', _('Povas vidi kategorioj de dokumentoj')),
            ('povas_krei_dokumentoj_kategorioj', _('Povas krei kategorioj de dokumentoj')),
            ('povas_forigi_dokumentoj_kategorioj', _('Povas forigi kategorioj de dokumentoj')),
            ('povas_shangxi_dokumentoj_kategorioj', _('Povas ŝanĝi kategorioj de dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id += 1
            super(model, self).__setattr__('id', next_id)

        super(DokumentoKategorio, self).save(force_insert=force_insert, force_update=force_update, using=using,
                                            update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_kategorioj', 
                'dokumentoj.povas_krei_dokumentoj_kategorioj',
                'dokumentoj.povas_forigi_dokumentoj_kategorioj',
                'dokumentoj.povas_shangxi_dokumentoj_kategorioj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_kategorioj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_kategorioj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_kategorioj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Типы связей категорий документов между собой, использует абстрактный класс UniversoBazaMaks
class DokumentoKategorioLigiloTipo(UniversoBazaMaks):

    # ID записи
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_kategorioj_dokumentoj_ligiloj_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de ligiloj de kategorioj de dokumentoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de ligiloj de kategorioj de dokumentoj')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_kategorioj_dokumentoj_ligiloj_tipoj',
             _('Povas vidi tipoj de ligiloj de kategorioj de dokumentoj')),
            ('povas_krei_dokumentoj_kategorioj_dokumentoj_ligiloj_tipoj',
             _('Povas krei tipoj de ligiloj de kategorioj de dokumentoj')),
            ('povas_forigi_dokumentoj_kategorioj_dokumentoj_ligiloj_tipoj',
             _('Povas forigi tipoj de ligiloj de kategorioj de dokumentoj')),
            ('povas_sxangxi_dokumentoj_kategorioj_dokumentoj_ligiloj_tipoj',
             _('Povas ŝanĝi tipoj de ligiloj de kategorioj de dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(DokumentoKategorioLigiloTipo, self).save(force_insert=force_insert, force_update=force_update,
                                          using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_kategorioj_dokumentoj_ligiloj_tipoj',
                'dokumentoj.povas_krei_dokumentoj_kategorioj_dokumentoj_ligiloj_tipoj',
                'dokumentoj.povas_forigi_dokumentoj_kategorioj_dokumentoj_ligiloj_tipoj',
                'dokumentoj.povas_sxangxi_dokumentoj_kategorioj_dokumentoj_ligiloj_tipoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_kategorioj_dokumentoj_ligiloj_tipoj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_kategorioj_dokumentoj_ligiloj_tipoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_kategorioj_dokumentoj_ligiloj_tipoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Связь категорий документов между собой, использует абстрактный класс UniversoBazaMaks
class DokumentoKategorioLigilo(UniversoBazaMaks):

    # категория документов владелец связи
    posedanto = models.ForeignKey(DokumentoKategorio, verbose_name=_('Kategorio - posedanto'), blank=False,
                                #   related_name='%(app_label)s_%(class)s_posedanto',
                                  related_name='dokumentoj_dokumentokategorioligilo_posedanto',
                                  null=False, default=None, on_delete=models.CASCADE)

    # связываемая категория документов
    ligilo = models.ForeignKey(DokumentoKategorio, verbose_name=_('Kategorio - ligilo'), blank=False, null=False,
                               default=None, related_name='dokumentoj_dokumentokategorioligilo_ligilo', on_delete=models.CASCADE)

    # тип связи категорий документов
    tipo = models.ForeignKey(DokumentoKategorioLigiloTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_kategorioj_dokumentoj_ligiloj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Ligilo de kategorioj de dokumentoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Ligiloj de kategorioj de dokumentoj')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_kategorioj_dokumentoj_ligiloj',
             _('Povas vidi ligiloj de kategorioj de dokumentoj')),
            ('povas_krei_dokumentoj_kategorioj_dokumentoj_ligiloj',
             _('Povas krei ligiloj de kategorioj de dokumentoj')),
            ('povas_forigi_dokumentoj_kategorioj_dokumentoj_ligiloj',
             _('Povas forigi ligiloj de kategorioj de dokumentoj')),
            ('povas_sxangxi_dokumentoj_kategorioj_dokumentoj_ligiloj',
             _('Povas ŝanĝi ligiloj de kategorioj de dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле uuid этой модели
        return '{}'.format(self.uuid)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_kategorioj_dokumentoj_ligiloj',
                'dokumentoj.povas_krei_dokumentoj_kategorioj_dokumentoj_ligiloj',
                'dokumentoj.povas_forigi_dokumentoj_kategorioj_dokumentoj_ligiloj',
                'dokumentoj.povas_sxangxi_dokumentoj_kategorioj_dokumentoj_ligiloj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_kategorioj_dokumentoj_ligiloj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_kategorioj_dokumentoj_ligiloj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_kategorioj_dokumentoj_ligiloj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Типы документов в, использует абстрактный класс UniversoBazaMaks
class DokumentoTipo(UniversoBazaMaks):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность или для которого создана сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # параллельный мир в котором есть эта сущность, может быть в нескольких
    realeco = models.ManyToManyField(Realeco, verbose_name=_('Realeco'),
                                     db_table='dokumentoj_tipoj_realeco_ligiloj')

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de dokumentoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de dokumentoj')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_tipoj', _('Povas vidi tipoj de dokumentoj')),
            ('povas_krei_dokumentoj_tipoj', _('Povas krei tipoj de dokumentoj')),
            ('povas_forigi_dokumentoj_tipoj', _('Povas forigi tipoj de dokumentoj')),
            ('povas_shangxi_dokumentoj_tipoj', _('Povas ŝanĝi tipoj de dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id += 1
            super(model, self).__setattr__('id', next_id)

        super(DokumentoTipo, self).save(force_insert=force_insert, force_update=force_update, using=using,
                                            update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_tipoj', 
                'dokumentoj.povas_krei_dokumentoj_tipoj',
                'dokumentoj.povas_forigi_dokumentoj_tipoj',
                'dokumentoj.povas_shangxi_dokumentoj_tipoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_tipoj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_tipoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_tipoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Виды документов, использует абстрактный класс UniversoBazaMaks
class DokumentoSpeco(UniversoBazaMaks):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # параллельный мир в котором есть эта сущность, может быть в нескольких
    realeco = models.ManyToManyField(Realeco, verbose_name=_('Realeco'),
                                     db_table='dokumentoj_specoj_realeco_ligiloj')

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_specoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Speco de dokumentoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Specoj de dokumentoj')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_specoj', _('Povas vidi specoj de dokumentoj')),
            ('povas_krei_dokumentoj_specoj', _('Povas krei specoj de dokumentoj')),
            ('povas_forigi_dokumentoj_specoj', _('Povas forigi specoj de dokumentoj')),
            ('povas_shangxi_dokumentoj_specoj', _('Povas ŝanĝi specoj de dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id += 1
            super(model, self).__setattr__('id', next_id)

        super(DokumentoSpeco, self).save(force_insert=force_insert, force_update=force_update, using=using,
                                            update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_specoj',
                'dokumentoj.povas_krei_dokumentoj_specoj',
                'dokumentoj.povas_forigi_dokumentoj_specoj',
                'dokumentoj.povas_shangxi_dokumentoj_specoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_specoj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_specoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_specoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Справочник документов, использует абстрактный класс UniversoBazaMaks
class Dokumento(UniversoBazaMaks):

    # ID записи
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность или для которого создана сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # категория документов 
    kategorio = models.ManyToManyField(DokumentoKategorio, verbose_name=_('Kategorio'),
                                       db_table='dokumentoj_kategorioj_ligiloj')

    # тип документов
    tipo = models.ForeignKey(DokumentoTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             related_name='dokumentoj_dokumento_tipo',
                            #  related_name='%(app_label)s_%(class)s_tipo',
                             on_delete=models.CASCADE)

    # вид документов
    speco = models.ForeignKey(DokumentoSpeco, verbose_name=_('Speco'), blank=True, null=True, default=None,
                              related_name='dokumentoj_dokumento_speco',
                              on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # параллельный мир в котором есть эта сущность, может быть в нескольких
    realeco = models.ManyToManyField(Realeco, verbose_name=_('Realeco'),
                                     db_table='dokumentoj_realeco_ligiloj')

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Dokumento')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Dokumentoj')
        # права
        permissions = (
            ('povas_vidi_dokumentoj', _('Povas vidi dokumentoj')),
            ('povas_krei_dokumentoj', _('Povas krei dokumentoj')),
            ('povas_forigi_dokumentoj', _('Povas forigi dokumentoj')),
            ('povas_shangxi_dokumentoj', _('Povas ŝanĝi dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id += 1
            super(model, self).__setattr__('id', next_id)

        super(Dokumento, self).save(force_insert=force_insert, force_update=force_update, using=using,
                                          update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj', 
                'dokumentoj.povas_krei_dokumentoj',
                'dokumentoj.povas_forigi_dokumentoj',
                'dokumentoj.povas_shangxi_dokumentoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Типы мест хранения документов, использует абстрактный класс UniversoBazaMaks
class DokumentoStokejoTipo(UniversoBazaMaks):

    # ID записи для вывода
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_stokejoj_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de stokejoj de dokumentoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de stokejoj de dokumentoj')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_stokejoj_tipoj',
             _('Povas vidi tipoj de stokejoj de dokumentoj')),
            ('povas_krei_dokumentoj_stokejoj_tipoj',
             _('Povas krei tipoj de stokejoj de dokumentoj')),
            ('povas_forigi_dokumentoj_stokejoj_tipoj',
             _('Povas forigi tipoj de stokejoj de dokumentoj')),
            ('povas_shangxi_dokumentoj_stokejoj_tipoj',
             _('Povas ŝanĝi tipoj de stokejoj de dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id += 1
            super(model, self).__setattr__('id', next_id)

        super(DokumentoStokejoTipo, self).save(force_insert=force_insert, force_update=force_update, using=using,
                                            update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_stokejoj_tipoj',
                'dokumentoj.povas_krei_dokumentoj_stokejoj_tipoj',
                'dokumentoj.povas_forigi_dokumentoj_stokejoj_tipoj',
                'dokumentoj.povas_shangxi_dokumentoj_stokejoj_tipoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_stokejoj_tipoj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_stokejoj_tipoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_stokejoj_tipoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Места хранения документов, использует абстрактный класс UniversoBazaMaks
class DokumentoStokejo(UniversoBazaMaks):

    # документ
    posedanto = models.ForeignKey(Dokumento, verbose_name=_('Dokumento posedanto'), blank=False, null=False,
                                #   related_name='%(app_label)s_%(class)s_posedanto',
                                  related_name='dokumentoj_dokumentostokejo_posedanto',
                                  default=None, on_delete=models.CASCADE)

    # уникальный личный ID места хранения
    id = models.IntegerField(_('ID'), blank=True, null=True, default=None)

    # тип места хранения документов на основе которого создано это место хранения документов
    tipo = models.ForeignKey(DokumentoStokejoTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             related_name='dokumentoj_dokumentostokejo_tipo',
                             on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_stokejoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Stokejo de dokumentoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Stokejoj de dokumentoj')
        # установка уникальности личного ID места хранения в рамках объекта
        unique_together = ("id", "posedanto")
        # права
        permissions = (
            ('povas_vidi_dokumentoj_stokejoj', _('Povas vidi stokejoj de dokumentoj')),
            ('povas_krei_dokumentoj_stokejoj', _('Povas krei stokejoj de dokumentoj')),
            ('povas_forigi_dokumentoj_stokejoj', _('Povas forigi stokejoj de dokumentoj')),
            ('povas_sxangxi_dokumentoj_stokejoj', _('Povas ŝanĝi stokejoj de dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле uuid этой модели
        return '{} ({})'.format(self.uuid, get_enhavo(self.priskribo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.filter(posedanto=self.posedanto).aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(DokumentoStokejo, self).save(force_insert=force_insert, force_update=force_update,
                                                 using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_stokejoj',
                'dokumentoj.povas_krei_dokumentoj_stokejoj',
                'dokumentoj.povas_forigi_dokumentoj_stokejoj',
                'dokumentoj.povas_sxangxi_dokumentoj_stokejoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_stokejoj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_stokejoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_stokejoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Типы владельцев документов, использует абстрактный класс UniversoBazaMaks
class DokumentoPosedantoTipo(UniversoBazaMaks):

    # уникальный личный ID
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_posedantoj_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de posedantoj de dokumentoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de posedantoj de dokumentoj')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_posedantoj_tipoj', _('Povas vidi tipoj de posedantoj de dokumentoj')),
            ('povas_krei_dokumentoj_posedantoj_tipoj', _('Povas krei tipoj de posedantoj de dokumentoj')),
            ('povas_forigi_dokumentoj_posedantoj_tipoj', _('Povas forigi tipoj de posedantoj de dokumentoj')),
            ('povas_sxangxi_dokumentoj_posedantoj_tipoj', _('Povas ŝanĝi tipoj de posedantoj de dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(DokumentoPosedantoTipo, self).save(force_insert=force_insert, force_update=force_update,
                                                   using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_posedantoj_tipoj',
                'dokumentoj.povas_krei_dokumentoj_posedantoj_tipoj',
                'dokumentoj.povas_forigi_dokumentoj_posedantoj_tipoj',
                'dokumentoj.povas_sxangxi_dokumentoj_posedantoj_tipoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_posedantoj_tipoj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_posedantoj_tipoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_posedantoj_tipoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Статус владельца документа, использует абстрактный класс UniversoBazaMaks
class DokumentoPosedantoStatuso(UniversoBazaMaks):

    # уникальный личный ID
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_posedantoj_statusoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Statuso de posedantoj de dokumentoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Statusoj de posedantoj de dokumentoj')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_posedantoj_statusoj',
             _('Povas vidi statusoj de posedantoj de dokumentoj')),
            ('povas_krei_dokumentoj_posedantoj_statusoj',
             _('Povas krei statusoj de posedantoj de dokumentoj')),
            ('povas_forigi_dokumentoj_posedantoj_statusoj',
             _('Povas forigi statusoj de posedantoj de dokumentoj')),
            ('povas_sxangxi_dokumentoj_posedantoj_statusoj',
             _('Povas ŝanĝi statusoj de posedantoj de dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(DokumentoPosedantoStatuso, self).save(force_insert=force_insert, force_update=force_update,
                                                      using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_posedantoj_statusoj',
                'dokumentoj.povas_krei_dokumentoj_posedantoj_statusoj',
                'dokumentoj.povas_forigi_dokumentoj_posedantoj_statusoj',
                'dokumentoj.povas_sxangxi_dokumentoj_posedantoj_statusoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_posedantoj_statusoj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_posedantoj_statusoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_posedantoj_statusoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Владельцы документов, использует абстрактный класс UniversoBazaRealeco
class DokumentoPosedanto(UniversoBazaRealeco):

    # документ владения
    dokumento = models.ForeignKey(Dokumento, verbose_name=_('Dokumento'), blank=False, null=False,
                                #   related_name='%(app_label)s_%(class)s_dokumento',
                                  related_name='dokumentoj_dokumentoposedanto_dokumento',
                                  default=None, on_delete=models.CASCADE)

    # пользователь владелец документа
    posedanto_uzanto = models.ForeignKey(Uzanto, verbose_name=_('Posedanta uzanto'), blank=True, null=True,
                                         related_name='dokumentoj_dokumentoposedanto_posedanto_uzanto',
                                         default=None, on_delete=models.CASCADE)

    # организация владелец документа
    posedanto_organizo = models.ForeignKey(Organizo, verbose_name=_('Posedanta organizo'), blank=True,
                                           related_name='dokumentoj_dokumentoposedanto_posedanto_organizo',
                                           null=True, default=None, on_delete=models.CASCADE)

    # тип владельца документа
    tipo = models.ForeignKey(DokumentoPosedantoTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             related_name='dokumentoj_dokumentoposedanto_tipo',
                             on_delete=models.CASCADE)

    # статус владельца документа
    statuso = models.ForeignKey(DokumentoPosedantoStatuso, verbose_name=_('Statuso'), blank=False, default=None,
                                related_name='dokumentoj_dokumentoposedanto_statuso',
                                on_delete=models.CASCADE)

    # размер доли владения
    parto = models.IntegerField(_('Parto'), blank=True, null=True, default=100)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_posedantoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Posedanto de dokumento')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Posedantoj de dokumentoj')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_posedantoj', _('Povas vidi posedantoj de dokumentoj')),
            ('povas_krei_dokumentoj_posedantoj', _('Povas krei posedantoj de dokumentoj')),
            ('povas_forigi_dokumentoj_posedantoj', _('Povas forigi posedantoj de dokumentoj')),
            ('povas_sxangxi_dokumentoj_posedantoj', _('Povas ŝanĝi posedantoj de dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле id владельца Siriuso и/или nomo организации владельца этой модели
        posedanto = "{}".format(self.dokumento.uuid)
        start = True
        if self.posedanto_uzanto:
            posedanto = "{}: {}".format(posedanto, self.posedanto_uzanto.id)
            start = False
        if self.posedanto_organizo:
            if start:
                posedanto = "{}: {}".format(posedanto, get_enhavo(self.posedanto_organizo.nomo, empty_values=True)[0])
            else:
                posedanto = "{}; {}".format(posedanto, get_enhavo(self.posedanto_organizo.nomo, empty_values=True)[0])
        return posedanto

    # реализация автоинкремента шаблона при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.sxablono_sistema:
            if self.sxablono_sistema_id is None or not self.sxablono_sistema_id:
                model = getattr(sys.modules[self.__module__], self.__class__.__name__)
                next_id = model.objects.all().aggregate(Max('sxablono_sistema_id'))['sxablono_sistema_id__max']

                if next_id is None:
                    next_id = 1
                else:
                    next_id = next_id + 1
                super(model, self).__setattr__('sxablono_sistema_id', next_id)

        super(DokumentoPosedanto, self).save(force_insert=force_insert, force_update=force_update,
                                                       using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_posedantoj',
                'dokumentoj.povas_krei_dokumentoj_posedantoj',
                'dokumentoj.povas_forigi_dokumentoj_posedantoj',
                'dokumentoj.povas_sxangxi_dokumentoj_posedantoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_posedantoj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_posedantoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_posedantoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Типы связей документов между собой, использует абстрактный класс UniversoBazaMaks
class DokumentoLigiloTipo(UniversoBazaMaks):

    # ID записи
    id = models.IntegerField(_('ID'), unique=True, default=0)

    # автор (пользователь, который создал сущность)
    autoro = models.ForeignKey(Uzanto, verbose_name=_('Aŭtoro'), blank=False, default=None,
                               on_delete=models.CASCADE)

    # название, многоязычное в JSON формате
    nomo = models.JSONField(verbose_name=_('Titolo'), blank=True, null=False, default=default_lingvo,
                            encoder=CallableEncoder)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                 encoder=CallableEncoder)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_ligiloj_tipoj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Tipo de ligiloj de dokumentoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Tipoj de ligiloj de dokumentoj')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_ligiloj_tipoj',
             _('Povas vidi tipoj de ligiloj de dokumentoj')),
            ('povas_krei_dokumentoj_ligiloj_tipoj',
             _('Povas krei tipoj de ligiloj de dokumentoj')),
            ('povas_forigi_dokumentoj_ligiloj_tipoj',
             _('Povas forigi tipoj de ligiloj de dokumentoj')),
            ('povas_sxangxi_dokumentoj_ligiloj_tipoj',
             _('Povas ŝanĝi tipoj de ligiloj de dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.id, get_enhavo(self.nomo, empty_values=True)[0])

    # реализация автоинкремента при сохранении
    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):

        if self.id is None or not self.id:
            model = getattr(sys.modules[self.__module__], self.__class__.__name__)
            next_id = model.objects.all().aggregate(Max('id'))['id__max']

            if next_id is None:
                next_id = 1
            else:
                next_id = next_id + 1
            super(model, self).__setattr__('id', next_id)

        super(DokumentoLigiloTipo, self).save(force_insert=force_insert, force_update=force_update,
                                          using=using, update_fields=update_fields)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_ligiloj_tipoj', 
                'dokumentoj.povas_krei_dokumentoj_ligiloj_tipoj',
                'dokumentoj.povas_forigi_dokumentoj_ligiloj_tipoj',
                'dokumentoj.povas_sxangxi_dokumentoj_ligiloj_tipoj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_ligiloj_tipoj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_ligiloj_tipoj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_ligiloj_tipoj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Связь документов между собой, использует абстрактный класс UniversoBazaMaks
class DokumentoLigilo(UniversoBazaMaks):

    # документ владелец связи
    posedanto = models.ForeignKey(Dokumento, verbose_name=_('Dokumento - posedanto'), blank=False, null=False,
                                  related_name='dokumentoj_dokumentoligilo_posedanto',
                                #   related_name='%(app_label)s_%(class)s_posedanto',
                                  default=None, on_delete=models.CASCADE)

    # место хранения владельца связи
    posedanto_stokejo = models.ForeignKey(DokumentoStokejo, verbose_name=_('Stokejo de posedanto'), blank=True,
                                          related_name='dokumentoj_dokumentoligilo_posedanto_stokejo',
                                          null=True, default=None, on_delete=models.CASCADE)

    # связываемый документ
    ligilo = models.ForeignKey(Dokumento, verbose_name=_('Dokumento - ligilo'), blank=False, null=False,
                               default=None, related_name='dokumentoj_dokumentoligilo_ligilo',
                               on_delete=models.CASCADE)

    # тип связи документов
    tipo = models.ForeignKey(DokumentoLigiloTipo, verbose_name=_('Tipo'), blank=False, default=None,
                             related_name='dokumentoj_dokumentoligilo_tipo',
                             on_delete=models.CASCADE)

    # описание, многоязычное в JSON формате
    priskribo = models.JSONField(verbose_name=_('Priskribo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # разъём (слот), который занимает этот объект у родительского объекта
    konektilo = models.IntegerField(_('Konektilo'), blank=True, null=True, default=None)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_ligiloj'
        # читабельное название модели, в единственном числе
        verbose_name = _('Ligilo de dokumentoj')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Ligiloj de dokumentoj')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_ligiloj', _('Povas vidi ligiloj de dokumentoj')),
            ('povas_krei_dokumentoj_ligiloj', _('Povas krei ligiloj de dokumentoj')),
            ('povas_forigi_dokumentoj_ligiloj', _('Povas forigi ligiloj de dokumentoj')),
            ('povas_sxangxi_dokumentoj_ligiloj', _('Povas ŝanĝi ligiloj de dokumentoj')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле uuid этой модели
        return '{}'.format(self.uuid)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_ligiloj', 
                'dokumentoj.povas_krei_dokumentoj_ligiloj',
                'dokumentoj.povas_forigi_dokumentoj_ligiloj',
                'dokumentoj.povas_sxangxi_dokumentoj_ligiloj'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_ligiloj')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_ligiloj')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_ligiloj'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Catalog_новаВидыУслугЭкспедирования "Виды Услуг Экспедирования" (Speco ,  (услу́га servo) )
class DokumentoSpecoServoEkspedo(SiriusoBazaAbstrakta3):

    # Code
    kodo = models.CharField(_('Kodo'), max_length=16, default=None, blank=True, null=True)

    # Description
    nomo = models.JSONField(verbose_name=_('Nomo'), blank=True, null=False, default=default_lingvo,
                            encoder=CallableEncoder)

    # ТипЦены
    tipo_kosto = models.JSONField(verbose_name=_('Tipo kosto'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # Валюта_Key
    mono_valuto = models.ForeignKey(MonoValuto, verbose_name=_("Mono valuto"), 
                                    related_name="dokumento_ekspedo_speco_servo_mono_valuto",
                                    blank=True, null=True,
                                    default=None, on_delete=models.CASCADE)

    # МаксВремяЧасПодачи (максима́льн||о maksimume)
    maks_tempo = models.IntegerField(_("Maksimume tempo"), default=None, blank=True, null=True)

    # Услуга_Key - ссылка на номенклатуру - не берём

    # ТипПосредническойУслуги (услу́га servo)
    tipo_servo = models.JSONField(verbose_name=_('Tipo servo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # НормаПробегаВЧас (пробе́г оч.сомнит. kurdistanco или mileage) (час horo)
    normo_mileage_horo = models.IntegerField(_("Normo mileage horo"), default=None, blank=True, null=True)

    # ЦенаПерепробегаЗаказчик
    kosto_mileage_kliento = models.FloatField(_("Kosto mileage kliento"), default=None, blank=True, null=True)

    # ЦенаПерепробегаПеревозчик (Перевозчик (на любом транспортном средстве) transportisto; veturigisto;)
    kosto_mileage_transportisto = models.FloatField(_("Kosto mileage klieanto"), default=None, blank=True, null=True)

    # НеПеревыставлять (Перевыставлять Re-prezenti)
    ne_re_prezenti = models.BooleanField(_("Ne re-prezenti"), blank=True, null=True, default=False)

    # НеВыводитьВРМ (Выводить eligi)
    ne_eligi = models.BooleanField(_("Ne eligi VRM"), blank=True, null=True, default=False)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_speco_servo_ekspedo'
        # читабельное название модели, в единственном числе
        verbose_name = _('Dokumento de ekspedo de servo de speco')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Dokumentoj de ekspedo de servo de speco')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_speco_servo_ekspedo', _('Povas vidi dokumentoj de ekspedo de servo de speco')),
            ('povas_krei_dokumentoj_speco_servo_ekspedo', _('Povas krei dokumentoj de ekspedo de servo de speco')),
            ('povas_forigi_dokumentoj_speco_servo_ekspedo', _('Povas forigi dokumentoj de ekspedo de servo de speco')),
            ('povas_shangxi_dokumentoj_speco_servo_ekspedo', _('Povas ŝanĝi dokumentoj de ekspedo de servo de speco')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}) {}'.format(self.kodo, get_enhavo(self.nomo, empty_values=True)[0])

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_speco_servo_ekspedo', 
                'dokumentoj.povas_krei_dokumentoj_speco_servo_ekspedo',
                'dokumentoj.povas_forigi_dokumentoj_speco_servo_ekspedo',
                'dokumentoj.povas_shangxi_dokumentoj_speco_servo_ekspedo'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_speco_servo_ekspedo')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_speco_servo_ekspedo')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_speco_servo_ekspedo'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Справочник характеристик документов Экспедирования (ekspedo), использует абстрактный класс UniversoBazaMaks
class DokumentoEkspedo(SiriusoBazaAbstrakta3):
    # Ref_Key   - uuid

    # характеристики к какому документу
    # dokumento = models.ForeignKey(Dokumento, verbose_name=_('Dokumento'), blank=True, null=True, default=None,
    dokumento = models.OneToOneField(Dokumento, verbose_name=_('Dokumento'), blank=True, null=True,
                                #   related_name='%(app_label)s_%(class)s_dokumento',
                                  related_name='dokumentoj_dokumentoekspedo_dokumento',
                                  on_delete=models.CASCADE)

    # Number номер заявки
    kodo = models.CharField(_('Kodo'), max_length=16, default=None, blank=True, null=True)

    # Адрес Выгрузки (вы́грузка elŝarĝado), многоязычное в JSON формате
    adreso_elsxargxado = models.JSONField(verbose_name=_('Adreso elsxargxado'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # Адрес Загрузки ((наполнение грузом) kargado), многоязычное в JSON формате
    adreso_kargado = models.JSONField(verbose_name=_('Adreso kargado'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # ВалютаЗаказчика_Key (валю́т||а valuto) (зака́з||чик (клиент) kliento)
    valuto_kliento = models.ForeignKey(MonoValuto, verbose_name=_("Valuto kliento"), 
                                       related_name="dokumentoj_dokumentoekspedo_valuto_kliento",
                                       blank=True, null=True,
                                       default=None, on_delete=models.CASCADE)


    # Вес
    pezo = models.IntegerField(_("Pezo"), default=None, blank=True, null=True)

    # ВремяВыгрузкиС (вре́м||я tempo) (вы́грузка elŝarĝado)
    tempo_elsxargxado = models.DateTimeField(_("Tempo elsxargxado"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # ВремяС
    tempo_s = models.DateTimeField(_("Tempo s"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # Грузоотправитель_Key (грузоотправи́тель ekspedinto) - указатель на организацию
    ekspedinto = models.ForeignKey(Organizo, verbose_name=_("Ekspedinto"), 
                                   related_name="dokumentoj_dokumentoekspedo_ekspedinto",
                                   blank=True, null=True,
                                   default=None, on_delete=models.CASCADE)

    # Грузополучатель_Key (грузополуча́тель ricevanto)
    ricevanto = models.ForeignKey(Organizo, verbose_name=_("Ricevanto"), 
                                  related_name="dokumentoj_dokumentoekspedo_ricevanto",
                                   blank=True, null=True,
                                   default=None, on_delete=models.CASCADE)

    # ДоговорЗаказчика_Key (догово́р (контракт) kontrakto)
    kontrakto_kliento = models.ForeignKey(Dokumento, verbose_name=_("Ricevanto"), 
                                          related_name="dokumentoj_dokumentoekspedo_kontrakto_kliento",
                                          blank=True, null=True,
                                          default=None, on_delete=models.CASCADE)


    # Заказчик_Key - uuid контрагента - организации 
    kliento = models.ForeignKey(Organizo, verbose_name=_("Kliento"), 
                                related_name='dokumentoj_dokumentoekspedo_kliento',
                                blank=True, null=True,
                                default=None, on_delete=models.CASCADE)

    # ЗаказчикИзвещен (извести́ть (дать знать) sciigi)
    kliento_sciigi = models.BooleanField(_("Kliento sciigi"), blank=True, null=True, default=None)

    # Комментарий
    komento = models.JSONField(verbose_name=_('Komento'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # КомментарийАдресаВыгрузки
    komento_adreso_elsxargxado = models.JSONField(verbose_name=_('Komento adreso elsxargxado'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # КомментарийАдресаЗагрузки
    komento_adreso_kargado = models.JSONField(verbose_name=_('Komento adreso kargado'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # КомментарийОтмены (отме́н||а nuligo)
    komento_nuligo = models.JSONField(verbose_name=_('Komento nuligo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # КонтактноеЛицоЗаказчика (kombatanto)
    kombatanto_kliento = models.ForeignKey(Kombatanto, verbose_name=_("Kombatanto kliento"), 
                                           related_name="dokumentoj_dokumentoekspedo_kombatanto_kliento",
                                           blank=True, null=True,
                                           default=None, on_delete=models.CASCADE)

    # КонтактноеЛицоПоАдресу - строка
    kombatanto_adresoj = models.JSONField(verbose_name=_('Kombatanto adreso'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # КонтактноеЛицоПоАдресуРазгрузки - строка
    kombatanto_adresoj_elsxargxado = models.JSONField(verbose_name=_('Kombatanto adreso elsxargxado'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # Объем (объём (величина в длину, ширину и высоту, выраженная в кубических единицах) volumeno)
    volumeno = models.FloatField(_("Volumeno"), blank=True, null=True, default=None)

    # ОписаниеГруза
    priskribo_kargo = models.JSONField(verbose_name=_('Priskribo kargo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # Организация_Key - ссылка на главную организацию
    organizo = models.ForeignKey(Organizo, verbose_name=_("Organizo"), 
                                     related_name='dokumentoj_dokumentoekspedo_organizo',
                                     blank=True, null=True,
                                     default=None, on_delete=models.CASCADE)

    # ОрганизацияПоАдресу - строка
    organizo_adreso = models.JSONField(verbose_name=_('Organizo adreso'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # ОрганизацияПоАдресуРазгрузки - строка
    organizo_adreso_elsxargxado = models.JSONField(verbose_name=_('Organizo adreso elsxargxado'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # ПричинаОтмены_Key - ссылка ??? (причи́н||а kaŭzo; kialo) (отме́н||а nuligo)
    kialo_nuligo_key = models.UUIDField(_('Kialo nuligo'), default=None, blank=True, null=True)

    # удалитьРезультатВыполнения_Key - ссылка (удали́ть forigi) (результа́т (чего-л.) rezulto) (выполн||е́ние plenumo)
    #  указывает на Catalog_новаСостоянияЗаявокЭкспедирования
    # Данное состояние храниться в проекте
    # Маршрут храниться в задачах проекта соответствующего документа

    # СтоимостьГруза (сто́имость kosto) 
    kosto_kargo = models.FloatField(_("Kosto kargo"), blank=True, null=True, default=None)

    # СуммаЗаказчика (су́мм||а sumo; ~а де́нег monsumo; )
    monsumo_kliento = models.FloatField(_("Monsumo kliento"), blank=True, null=True, default=None)

    # СуммаЗаказчикаУстановленаВручную (устано́вленный fiksa) (вручну́ю (per)mane)
    monsumo_kliento_fiksa_mane = models.BooleanField(_("Monsumo kliento fiksa mane"), blank=True, null=True, default=None)

    # СуммаПеревозчика (Перевозчик (на любом транспортном средстве) transportisto; veturigisto;)
    monsumo_transportisto = models.FloatField(_("Monsumo transportisto"), blank=True, null=True, default=None)

    # СуммаПеревозчикаУстановленаВручную 
    monsumo_transportisto_fiksa_mane = models.BooleanField(_("Monsumo transportisto fiksa mane"), blank=True, null=True, default=None)

    # ТелефонЗаказчика
    telefono_kliento = models.JSONField(verbose_name=_('Telefono kliento'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # ТелефонПоАдресу
    telefono_adreso = models.JSONField(verbose_name=_('Telefono adreso'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # ТелефонПоАдресуРазгрузки
    telefono_adreso_elsxargxado = models.JSONField(verbose_name=_('Telefono adreso elsxargxado'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # Факт
    fakto = models.BooleanField(_("Fakto"), blank=True, null=True, default=None)

    # ЦенаЗаказчика (цен||а́ prezo; (стоимость) kosto)
    kosto_kliento = models.FloatField(_("Kosto kliento"), blank=True, null=True, default=None)

    # ЦенаПеревозчика
    kosto_transportisto = models.FloatField(_("Kosto transportisto"), blank=True, null=True, default=None)

    # АвансЗаказчика (ава́нс parta antaŭpago, partopago)
    partopago_kliento = models.FloatField(_("Partopago kliento"), blank=True, null=True, default=None)

    # АвансПеревозчику
    partopago_transportisto = models.FloatField(_("Partopago transportisto"), blank=True, null=True, default=None)

    # ДопУсловия (дополни́тельный aldona) (усло́вия kondiĉaro)
    aldona_kondicxaro = models.JSONField(verbose_name=_('Aldona kondicxaro'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # СтавкаНДСЗаказчик (Ставка нало́говая ~а impost(o)kvoto;)
    impostokvoto_kliento = models.JSONField(verbose_name=_('Impostokvoto kliento'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # СтавкаНДСПеревозчик
    impostokvoto_transportisto = models.JSONField(verbose_name=_('Impostokvoto transportisto'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # КомментарийРасчета (расчёт kalkulo; kalkulado)
    priskribo_kalkulado = models.JSONField(verbose_name=_('Priskribo kalkulado'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)
    
    # СборныйГруз (Сборное ме́сто - rendevuejo)
    rendevuejo = models.BooleanField(_("Rendevuejo"), blank=True, null=True, default=None)

    # НомерНакладнойСК (накладна́я сущ. (на перевозимый груз) frajtoletero)
    numero_frajtoletero = models.JSONField(verbose_name=_('Numero frajtoletero'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # ВесФакт (вес - pezo)
    pezo_fakto = models.FloatField(_("Pezo fakto"), blank=True, null=True, default=None)

    # ВесРасч (расчёт||ный kalkula)
    pezo_kalkula = models.FloatField(_("Pezo kalkula"), blank=True, null=True, default=None)

    # ОпасныйГруз (представляющий опасность - danĝera)
    dangxera_kargo = models.BooleanField(_("Dangxera kargo"), blank=True, null=True, default=None)

    # ОписаниеОпасногоГруза
    priskribo_dangxera_kargo = models.JSONField(verbose_name=_('Priskribo dangxera kargo'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # КлассОпасности
    klaso_dangxera = models.JSONField(verbose_name=_('Klaso dangxera'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # ВозвратТСД (Возврат retropaŝo)
    retropasxo_tsd = models.BooleanField(_("Retropasxo TSD"), blank=True, null=True, default=None)

    # ПриемДоставкаВНерабочееВремя (Прием akcepto) (Доставка liveri) (нерабочий nelabora) (Время tempo)
    akcepto_liveri_nelabora_tempo = models.BooleanField(_("Akcepto liveri nelabora tempo"), blank=True, null=True, default=None)

    # ДополнительнаяУпаковка (Упаковка  (материал) pakumo)
    aldone_pakumo = models.BooleanField(_("Aldone pakumo"), blank=True, null=True, default=None)

    # ТемпературныйРежим_Key
    temperatura_reghimo = models.ForeignKey(ObjektoTemperaturaReghimo, verbose_name=_("Temperatura reghimo"), 
                                            related_name="dokumentoj_dokumentoekspedo_temperatura_reghimo",
                                            blank=True, null=True,
                                            default=None, on_delete=models.CASCADE)

    # СозданиеХЦ_Key (Создание - faro)
    faro_hc_key = models.UUIDField(_('Faro HC UUID'), default=None, blank=True, null=True)

    # ДатчикТемпературы (Датчик - indikatoro)
    indikatoro_temperatura = models.BooleanField(_("Indikatoro temperatura"), blank=True, null=True, default=None)

    # ПредоставлениеТП (Предоставление - livero)
    livero_tp = models.BooleanField(_("Livero TP"), blank=True, null=True, default=None)

    # ДопТребованияХЦ (тре́бовани||е postulo)
    aldone_postulo_hc = models.JSONField(verbose_name=_('Aldone postulo HC'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder)

    # ГородПриемки (приём (многократное или длительное действие) ricevado)
    urboj_recivado = models.ForeignKey(InformilojUrboj, verbose_name=_("Urboj recivado"), 
                                       related_name="dokumentoj_dokumentoekspedo_urboj_recivado",
                                       blank=True, null=True,
                                       default=None, on_delete=models.CASCADE)

    # ГородПриемки_nomo (приём (многократное или длительное действие) ricevado)
    urboj_recivado_nomo = models.JSONField(verbose_name=_('Nomo urboj recivado'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder) 

    # ГородПередачи (переда́ча  (отдание через посредника или являясь посредником) transdono)
    urboj_transdono = models.ForeignKey(InformilojUrboj, verbose_name=_("Urboj transdono"), 
                                        related_name="dokumentoj_dokumentoekspedo_urboj_transdono",
                                        blank=True, null=True,
                                        default=None, on_delete=models.CASCADE)

    # ГородПередачи_nomo (переда́ча  (отдание через посредника или являясь посредником) transdono)
    urboj_transdono_nomo = models.JSONField(verbose_name=_('Nomo urboj transdono'), blank=True, null=False, default=default_lingvo,
                              encoder=CallableEncoder) 

    # ИныеУслуги (иной (другой) alia) (услу́га servo)
    aliaj_servo = models.JSONField(verbose_name=_('Aliaj servo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # ПередачаГрузаФИО (переда́ча (отдание) fordono)
    fordono_kargo_fio = models.JSONField(verbose_name=_('FIO fordono kargo'), blank=True, null=False, default=default_lingvo,
                                   encoder=CallableEncoder)

    # ФПередачаГрузаДата
    fordono_kargo_dato = models.DateField(_("Dato fordono kargo"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # ФПередачаГрузаВремя
    fordono_kargo_tempo = models.TimeField(_("Tempo fordono kargo"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # СКЛ_ДатаПриемки (склад konservejo)
    konservejo_ricevado_dato = models.DateField(_("Dato konservejo ricevado"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # СКЛ_ВремяПриемкиС (c - de)
    konservejo_ricevado_tempo_de = models.TimeField(_("Tempo de konservejo ricevado"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # СКЛ_ВремяПриемкиПо (по - en)
    konservejo_ricevado_tempo_en = models.TimeField(_("Tempo en konservejo ricevado"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # СКЛ_ДатаПередачи (склад konservejo)
    konservejo_fordono_dato = models.DateField(_("Dato konservejo fordono"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # СКЛ_ВремяПередачиС (c - de)
    konservejo_fordono_tempo_de = models.TimeField(_("Tempo de konservejo fordono"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # СКЛ_ВремяПередачиПо (по - en)
    konservejo_fordono_tempo_en = models.TimeField(_("Tempo en konservejo fordono"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # ТребуетсяСтрахование (тре́бовать (постоянно) postuladi.) (страхова́||ние asekurado)
    asekurado = models.BooleanField(_("Asekurado"), blank=True, null=True, default=False)

    # КоличествоЧасовГрузчики (гру́зчик ŝarĝisto) (час 1. horo)
    horoj_sxargxistoj = models.IntegerField(_("Horoj sxargxistoj"), default=None, blank=True, null=True)

    # КоличествоГрузчиков (Количество kvanto)
    kvanto_sxargxistoj = models.IntegerField(_("Kvanto sxargxistoj"), default=None, blank=True, null=True)

    # КоличествоМест ( (предмет багажа) peco)
    kvanto_pecoj = models.IntegerField(_("Kvanto pecoj"), default=None, blank=True, null=True)

    # ТребуютсяГрузчикиТакелажники (такела́ж мор. (совокупность приспособлений) rigilaro;)
    sxargxisto_rigilaro = models.IntegerField(_("Sxargxisto rigilaro"), default=None, blank=True, null=True)

    # Тяжеловес (en peza kategorio)
    en_peza_kategorio = models.BooleanField(_("En peza kategorio"), blank=True, null=True, default=False)

    # НаименованиеГруза
    nomo_kargo = models.JSONField(verbose_name=_('Nomo kargo'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # Транспорт_Key (тра́нспорт trajno)
    trajno_key = models.UUIDField(_('Trajno UUID'), default=None, blank=True, null=True)

    # Водитель_Key (Водитель kondukisto)
    kondukisto_key = models.UUIDField(_('Kondukisto UUID'), default=None, blank=True, null=True)

    # скл_ТемпературныйРежим1  +2+25
    konservejo_temperatura_reghimo_1 = models.BooleanField(_("Konservejo temperatura reghimo 1"), blank=True, null=True, default=False)

    # скл_ТемпературныйРежим2  +2+8
    konservejo_temperatura_reghimo_2 = models.BooleanField(_("Konservejo temperatura reghimo 2"), blank=True, null=True, default=False)

    # скл_ТемпературныйРежим3  -20
    konservejo_temperatura_reghimo_3 = models.BooleanField(_("Konservejo temperatura reghimo 3"), blank=True, null=True, default=False)

    # скл_ТемпературныйРежим4  -70
    konservejo_temperatura_reghimo_4 = models.BooleanField(_("Konservejo temperatura reghimo 4"), blank=True, null=True, default=False)

    # скл_ТемпературныйРежимИной 
    konservejo_temperatura_reghimo_alia = models.JSONField(verbose_name=_('Konservejo temperatura reghimo alia'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # скл_ТемпературныйРежим5  
    konservejo_temperatura_reghimo_5 = models.BooleanField(_("Konservejo temperatura reghimo 5"), blank=True, null=True, default=False)

    # скл_ТемпературныйРежим6
    konservejo_temperatura_reghimo_6 = models.BooleanField(_("Konservejo temperatura reghimo 6"), blank=True, null=True, default=False)

    # скл_Задание (зада́ни||е tasko)
    konservejo_tasko = models.JSONField(verbose_name=_('Konservejo tasko'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # УИД (идентификатор Битрикс)
    uid = models.CharField(verbose_name=_('UID'), max_length=50, blank=True, null=True, default=None)

    # скл_Комментарий
    konservejo_komento = models.JSONField(verbose_name=_('Konservejo komento'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # рл_Поставщик_Key (Поставщик liveranto)
    liveranto = models.ForeignKey(Organizo, verbose_name=_("Urboj transdono"), 
                                  related_name="dokumentoj_dokumentoekspedo_liveranto",
                                  blank=True, null=True,
                                  default=None, on_delete=models.CASCADE)

    # рл_ДоговорПоставщика_Key
    liveranto_kontrakto = models.ForeignKey(Dokumento, verbose_name=_("Kontrakto liveranto"), 
                                            related_name="%(app_label)s_%(class)s_liveranto_kontrakto",
                                            blank=True, null=True,
                                            default=None, on_delete=models.CASCADE)

    # рл_КонтактноеЛицоПоставщика_Key
    kombatanto_kontrakto = models.ForeignKey(Kombatanto, verbose_name=_("Kombatanto kontrakto"), 
                                             related_name="dokumentoj_dokumentoekspedo_kombatanto_kontrakto",
                                             blank=True, null=True,
                                             default=None, on_delete=models.CASCADE)

    # рл_ДатаПодачиТранспорт (Подача (подгон к указанному месту: машины, экипажа и т.п.) venigo;)
    trajno_venigo_dato = models.DateField(_("Dato venigo trajno"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # рл_ВремяПодачиТранспорт
    trajno_venigo_tempo = models.TimeField(_("Tempo venigo trajno"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # рл_ДатаОкончанияТранспорт (Окончания  (наступление конца) finiĝo)
    trajno_finigho_dato = models.DateField(_("Dato finigho trajno"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # рл_ВремяОкончанияТранспорт
    trajno_finigho_tempo = models.TimeField(_("Tempo finigho trajno"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # ТранспортСоСкладаГК_Key (тра́нспорт trajno)
    trajno_konservejo_gk_key = models.UUIDField(_('Trajno konservejo gk UUID'), default=None, blank=True, null=True)

    # ВодительСоСкладаГК_Key (Водитель kondukisto)
    kondukisto_konservejo_gk_key = models.UUIDField(_('Kondukisto konservejo gk UUID'), default=None, blank=True, null=True)

    # ДатчикТемпературы2  (да́тчик тех. (преобразователь сигнала) signaltransformilo; (индикатор) indikatoro; (сенсор) sensoro;)  (температу́р||а temperaturo)
    sensoro_temperatura_2 = models.BooleanField(_("Sensoro temperatura 2"), blank=True, null=True, default=False)

    # ДатчикТемпературы3  (да́тчик тех. (преобразователь сигнала) signaltransformilo; (индикатор) indikatoro; (сенсор) sensoro;)  (температу́р||а temperaturo)
    sensoro_temperatura_3 = models.BooleanField(_("Sensoro temperatura 3"), blank=True, null=True, default=False)

    # ДатчикТемпературы4  (да́тчик тех. (преобразователь сигнала) signaltransformilo; (индикатор) indikatoro; (сенсор) sensoro;)  (температу́р||а temperaturo)
    sensoro_temperatura_4 = models.BooleanField(_("Sensoro temperatura 4"), blank=True, null=True, default=False)

    # ДатчикТемпературы5  (да́тчик тех. (преобразователь сигнала) signaltransformilo; (индикатор) indikatoro; (сенсор) sensoro;)  (температу́р||а temperaturo)
    sensoro_temperatura_5 = models.BooleanField(_("Sensoro temperatura 5"), blank=True, null=True, default=False)

    # ДатчикТемпературыИной  (да́тчик тех. (преобразователь сигнала) signaltransformilo; (индикатор) indikatoro; (сенсор) sensoro;)  (температу́р||а temperaturo)
    sensoro_temperatura_alia = models.BooleanField(_("Sensoro temperatura alia"), blank=True, null=True, default=False)

    # ПредоставлениеТП2  (да́тчик тех. (преобразователь сигнала) signaltransformilo; (индикатор) indikatoro; (сенсор) sensoro;)  (температу́р||а temperaturo)
    Livero_tp_2 = models.BooleanField(_("livero TP 2"), blank=True, null=True, default=False)

    # ПредоставлениеТП3  (да́тчик тех. (преобразователь сигнала) signaltransformilo; (индикатор) indikatoro; (сенсор) sensoro;)  (температу́р||а temperaturo)
    Livero_tp_3 = models.BooleanField(_("livero TP 3"), blank=True, null=True, default=False)

    # ПредоставлениеТП4  (да́тчик тех. (преобразователь сигнала) signaltransformilo; (индикатор) indikatoro; (сенсор) sensoro;)  (температу́р||а temperaturo)
    Livero_tp_4 = models.BooleanField(_("livero TP 4"), blank=True, null=True, default=False)

    # ПредоставлениеТП5  (да́тчик тех. (преобразователь сигнала) signaltransformilo; (индикатор) indikatoro; (сенсор) sensoro;)  (температу́р||а temperaturo)
    Livero_tp_5 = models.BooleanField(_("livero TP 5"), blank=True, null=True, default=False)

    # ПредоставлениеТПИной  (да́тчик тех. (преобразователь сигнала) signaltransformilo; (индикатор) indikatoro; (сенсор) sensoro;)  (температу́р||а temperaturo)
    Livero_tp_alia = models.BooleanField(_("livero TP alia"), blank=True, null=True, default=False)

    # скл_КомментарийКлиента 
    priskribo_kliento = models.JSONField(verbose_name=_('Priskribo kliento'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # НомерНакладнойКлиента
    numero_frajtoletero_kliento = models.JSONField(verbose_name=_('Numero frajtoletero kliento'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # EmailОтправителя (отправи́тель (отправивший) ekspedinto;)
    email_ekspedinto = models.JSONField(verbose_name=_('e-mail ekspedinto'), blank=True, null=False, default=default_lingvo,
                                        encoder=CallableEncoder)

    # EmailПолучателя (получа́тель ricevanto;)
    email_ricevanto = models.JSONField(verbose_name=_('e-mail ricevanto'), blank=True, null=False, default=default_lingvo,
                                        encoder=CallableEncoder)

    # ДатаНаИсполнении (исполн||е́ние 1. (действие исполняющего; способ) plenumo; plenumado)
    plenumado_dato = models.DateTimeField(_("Dato plenumado"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # рл_СтационарныйТермописец (Стационарный - fiksa) (Термописец - (термо - termo) (записывать) skribi)
    fiksa_termoskribi = models.BooleanField(_("Fiksa termoskribi"), blank=True, null=True, default=False)

    # рл_СтационарныйТермописец2
    fiksa_termoskribi_2 = models.BooleanField(_("Fiksa termoskribi 2"), blank=True, null=True, default=False)

    # рл_СтационарныйТермописец3
    fiksa_termoskribi_3 = models.BooleanField(_("Fiksa termoskribi 3"), blank=True, null=True, default=False)

    # рл_СтационарныйТермописец4
    fiksa_termoskribi_4 = models.BooleanField(_("Fiksa termoskribi 4"), blank=True, null=True, default=False)

    # рл_СтационарныйТермописец5
    fiksa_termoskribi_5 = models.BooleanField(_("Fiksa termoskribi 5"), blank=True, null=True, default=False)

    # рл_СтационарныйТермописецИной
    fiksa_termoskribi_alia = models.BooleanField(_("Fiksa termoskribi alia"), blank=True, null=True, default=False)

    # рл_ТипЗаявки (за́явк||а (заказ) mendo)
    tipo_mendo = models.JSONField(verbose_name=_('Tipo mendo'), blank=True, null=False, default=default_lingvo,
                                        encoder=CallableEncoder)

    # рл_ПодразделениеЗаказчика_Key (Подразделение  (отдел, раздел, секция) sekcio)
    sekcio_kliento_key = models.UUIDField(_('Sekcio kliento UUID'), default=None, blank=True, null=True)

    # рл_ГрузчикиПогрузка (погру́зка ŝarĝado)
    sxargxistoj_sxargxado = models.BooleanField(_("Sxargxistoj sxargxado"), blank=True, null=True, default=False)

    # рл_ГрузчикиВыгрузка (вы́грузка elŝarĝado)
    sxargxistoj_elsxargxado = models.BooleanField(_("Sxargxistoj elsxargxado"), blank=True, null=True, default=False)

    # файлы к данной заявке
    dosiero = models.ManyToManyField(DokumentoDosiero, verbose_name=_("Dosiero"), 
                                             db_table="dokumentoj_dokumentoekspedo_dosiero")

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_ekspedo'
        # читабельное название модели, в единственном числе
        verbose_name = _('Dokumento de ekspedo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Dokumentoj de ekspedo')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_ekspedo', _('Povas vidi dokumentoj de ekspedo')),
            ('povas_krei_dokumentoj_ekspedo', _('Povas krei dokumentoj de ekspedo')),
            ('povas_forigi_dokumentoj_ekspedo', _('Povas forigi dokumentoj de ekspedo')),
            ('povas_shangxi_dokumentoj_ekspedo', _('Povas ŝanĝi dokumentoj de ekspedo')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}'.format(self.uuid)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            if user_obj.is_superuser:
                all_perms = Permission.objects.filter(content_type__app_label='dokumentoj')
            else:
                # выбрать права, какие относятся к моделе
                model_perms = set([
                    'povas_vidi_dokumentoj_ekspedo', 
                    'povas_krei_dokumentoj_ekspedo',
                    'povas_forigi_dokumentoj_ekspedo',
                    'povas_shangxi_dokumentoj_ekspedo'
                ])
                # выбираем права, какие есть у пользователя по данной моделе
                all_perms = set(user_obj.user_permissions.filter(
                    content_type__app_label='dokumentoj', codename__in=model_perms).values_list('codename', flat=True))

                # ЗДЕСЬ начинается блок добавления прав согласно условиям пользователя !!!
                # если сотрудник предприятия, то имеет все права
                membro = OrganizoMembro.objects.get(organizo__in=[self.organizo, self.kliento], uzanto=user_obj, forigo=False,
                                                    arkivo=False, publikigo=True)
                if membro:
                    all_perms = all_perms.union({
                        'povas_vidi_dokumentoj_ekspedo',
                        'povas_krei_dokumentoj_ekspedo',
                        'povas_forigi_dokumentoj_ekspedo',
                        'povas_shangxi_dokumentoj_ekspedo'
                    })
            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        uzanto = user_obj
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_ekspedo')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_ekspedo')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если член организации-владельца (клиента), то выдаём по нему данные
                cond = Q(kliento__organizomembro__uzanto__id=uzanto.id) | Q(organizo__organizomembro__uzanto__id=uzanto.id)
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                # cond = Q(uuid__isnull=True)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_ekspedo'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# Catalog_ДоговорыКонтрагентов  документов договоры контрагентов (ekspedo)
class DokumentoContract(SiriusoBazaAbstrakta3):

    sekso_choices = (
        ('vira', _('Vira')),
        ('virina', _('Virina'))
    )

    # характеристики к какому документу
    dokumento = models.ForeignKey(Dokumento, verbose_name=_('Dokumento'), blank=True, null=True, default=None,
                                  related_name='%(app_label)s_%(class)s_dokumento',
                                  on_delete=models.CASCADE)

    # Code
    kodo = models.CharField(_('Kodo'), max_length=16, default=None, blank=True, null=True)

    # ВалютаВзаиморасчетов_Key
    mono_valuto = models.ForeignKey(MonoValuto, verbose_name=_("Mono valuto"), 
                                    related_name="%(app_label)s_%(class)s_mono_valuto",
                                    blank=True, null=True,
                                    default=None, on_delete=models.CASCADE)

    # Организация_Key
    organizo = models.ForeignKey(Organizo, verbose_name=_('Organizo'), blank=True,
                                           related_name='%(app_label)s_%(class)s_organizo',
                                           null=True, default=None, on_delete=models.CASCADE)

    # ПроцентКомиссионногоВознаграждения (комиссио́нное вознагражде́ние komisipago, komisimono, provizio)
    komisipago = models.FloatField(_("Komisipago"), default=None, blank=True, null=True)

    # СпособРасчетаКомиссионногоВознаграждения (способ расчета - kalkulo metodo) 
    komisipago_kalkulo_metodo = models.JSONField(verbose_name=_('Komisipago kalkulo metodo'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # ВидДоговора (Tipo de Kontrakto)
    tipo_kontrakto = models.JSONField(verbose_name=_('Tipo de Kontrakto'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    #УчетАгентскогоНДС (Kontado Agentejo Financoj)
    kontado_agentejo = models.BooleanField(_("Kontado agentejo financoj"), blank=True, null=True, default=False)

    # ВидАгентскогоДоговора (Tipo de Agentejo Interkonsento)
    tipo_agentejo = models.JSONField(verbose_name=_('Tipo de agentejo interkonsento'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # РасчетыВУсловныхЕдиницах (Kalkulo de Kondiĉa unuoj)
    kalkuto_kondicxa_unioj = models.BooleanField(_("Kalkulo de kondiĉa unuoj"), blank=True, null=True, default=False)

    # УдалитьРеализацияНаЭкспорт (Forigi La Efektivigo Por Eksportado)
    forigi_eksportado = models.BooleanField(_("Forigi la efektivigo por eksportado"), blank=True, null=True, default=False)

    # Дата
    dato = models.DateTimeField(_("Dato"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # Номер
    nombro = models.JSONField(verbose_name=_('Nombro'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # СрокДействия (Valideca Periodo)
    valideca_periodo = models.DateField(_("Valideca periodo"), auto_now=False, auto_now_add=False, blank=True, null=True)

    # УстановленСрокОплаты (La Paga Templimo Estis Fiksita)
    fiksita_paga_termino = models.BooleanField(_("La paga templimo estis fiksita"), blank=True, null=True, default=False)

    # СрокОплаты (Paga termino)
    paga_termino = models.IntegerField(_("Paga termino"), default=None, blank=True, null=True)

    # ПорядокРегистрацииСчетовФактурНаАвансПоДоговору (Procedo Por Registriĝo De Fakturoj Por Antaŭas Pago Sub La Kontrakto)
    procedo_registrigho = models.JSONField(verbose_name=_('Procedo Por Registriĝo De Fakturoj Por Antaŭas Pago Sub La Kontrakto'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # Валютный
    valuta = models.BooleanField(_("Valuta"), blank=True, null=True, default=False)

    # ОплатаВВалюте
    pagado_valuta = models.BooleanField(_("Pagado de valuta"), blank=True, null=True, default=False)

    # ЗаРуководителяПоПриказу (direktanto ordonilo (приказ))
    direktanto_ordonilo = models.JSONField(verbose_name=_('FIO direktanto de ordonilo'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # ДоговорПодписан (subskribi kontrakton )
    subskribi_kontrakton = models.BooleanField(_("Subskribi kontrakton"), blank=True, null=True, default=False)

    # РуководительКонтрагента
    direktanto_kombaranto = models.JSONField(verbose_name=_('Direktanto kombaranto'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # ДолжностьРуководителяКонтрагента (Должность - ofico)
    direktanto_kombaranto_ofico = models.JSONField(verbose_name=_('Ofico de direktanto de kombaranto'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # sekso ПолРуководителяКонтрагента
    sekso_direktanto_kombaranto = models.CharField(_('Sekso de direktanto de kombaranto'), max_length=6, choices=sekso_choices, blank=True, null=True)

    # файлы к данному договору
    dosiero = models.ManyToManyField(DokumentoDosiero, verbose_name=_("Dosiero"), 
                                             db_table="dokumentoj_dokumentocontract_dosiero")

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_contract'
        # читабельное название модели, в единственном числе
        verbose_name = _('Dokumento de contract')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Dokumentoj de contract')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_contract', _('Povas vidi dokumentoj de contract')),
            ('povas_krei_dokumentoj_contract', _('Povas krei dokumentoj de contract')),
            ('povas_forigi_dokumentoj_contract', _('Povas forigi dokumentoj de contract')),
            ('povas_shangxi_dokumentoj_contract', _('Povas ŝanĝi dokumentoj de contract')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}'.format(self.uuid)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_contract', 
                'dokumentoj.povas_krei_dokumentoj_contract',
                'dokumentoj.povas_forigi_dokumentoj_contract',
                'dokumentoj.povas_shangxi_dokumentoj_contract'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        uzanto = user_obj
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_contract')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_contract')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если член организации-владельца (клиента), то выдаём по нему данные
                cond = Q(ekspedo__kliento__organizomembro__uzanto__id=uzanto.id)
        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_contract'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# ГрузыММП характеристик документов Экспедирования (ekspedo), использует абстрактный класс SiriusoBazaAbstrakta3
class DokumentoEkspedoKargo(SiriusoBazaAbstrakta3):

    # LineNumber
    numero = models.IntegerField(_("Numero"), default=None, blank=True, null=True)

    # Наименование
    nomo = models.JSONField(verbose_name=_('Nomo'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # КоличествоМест ( (предмет багажа) peco)
    kvanto_pecoj = models.IntegerField(_("Kvanto pecoj"), default=None, blank=True, null=True)

    # Длина
    longo = models.FloatField(_("Longo"), default=None, blank=True, null=True)

    # Ширина (larĝo)
    largho = models.FloatField(_("Largho"), default=None, blank=True, null=True)

    # Высота
    alto = models.FloatField(_("Alto"), default=None, blank=True, null=True)

    # ВесФактический (факти́чески fakte; ~й fakta)
    pezo_fakta = models.FloatField(_("Pezo fakta"), default=None, blank=True, null=True)

    # Объем
    volumeno = models.FloatField(_("Volumeno"), default=None, blank=True, null=True)

    # ВесОбъемный
    pezo_volumena = models.FloatField(_("Pezo volumena"), default=None, blank=True, null=True)

    # ТипУпаковки_Key
    tipo_pakumoj = models.ForeignKey(ObjektoTipoPakumo, verbose_name=_("Tipo pakumoj"), 
                                            related_name="dokumento_ekspedo_kargo_tipo_pakumoj",
                                            blank=True, null=True,
                                            default=None, on_delete=models.CASCADE)
    # НуженДатчик
    indikatoro = models.BooleanField(_("Indikatoro"), blank=True, null=True, default=False)

    # СерийныйНомерДатчика
    numero_indikatoro = models.JSONField(verbose_name=_('Numero indikatoro'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # Терморежим_Key
    temperatura_reghimo = models.ForeignKey(ObjektoTemperaturaReghimo, verbose_name=_("Temperatura reghimo"), 
                                            related_name="dokumento_ekspedo_kargo_temperatura_reghimo",
                                            blank=True, null=True,
                                            default=None, on_delete=models.CASCADE)

    # ОпасныйНеопасный
    grave = models.BooleanField(_("Grave"), blank=True, null=True, default=False)

    # ВозвратУпаковки
    retropasxo_pakumo = models.BooleanField(_("Retropasxo pakumo"), blank=True, null=True, default=False)

    # ВозвратДатчика
    retropasxo_indikatoro = models.BooleanField(_("Retropasxo indikatoro"), blank=True, null=True, default=False)

    # Датчик_Key
    indikatoro_key = models.UUIDField(_('Indikatoro UUID'), default=None, blank=True, null=True)

    # от какой заявки
    ekspedo = models.ForeignKey(DokumentoEkspedo, verbose_name=_("Ekspedo"), 
                                related_name="dokumento_ekspedo_kargo_ekspedo",
                                blank=True, null=True,
                                default=None, on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_ekspedo_kargo'
        # читабельное название модели, в единственном числе
        verbose_name = _('Dokumento de ekspedo de kargo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Dokumentoj de ekspedo de kargo')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_ekspedo_kargo', _('Povas vidi dokumentoj de ekspedo de kargo')),
            ('povas_krei_dokumentoj_ekspedo_kargo', _('Povas krei dokumentoj de ekspedo de kargo')),
            ('povas_forigi_dokumentoj_ekspedo_kargo', _('Povas forigi dokumentoj de ekspedo de kargo')),
            ('povas_shangxi_dokumentoj_ekspedo_kargo', _('Povas ŝanĝi dokumentoj de ekspedo de kargo')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}'.format(self.uuid)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_ekspedo_kargo', 
                'dokumentoj.povas_krei_dokumentoj_ekspedo_kargo',
                'dokumentoj.povas_forigi_dokumentoj_ekspedo_kargo',
                'dokumentoj.povas_shangxi_dokumentoj_ekspedo_kargo'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        uzanto = user_obj
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_ekspedo_kargo')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_ekspedo_kargo')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если член организации-владельца (клиента), то выдаём по нему данные
                cond = Q(ekspedo__kliento__organizomembro__uzanto__id=uzanto.id)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_ekspedo_kargo'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# скл_Грузы характеристик документов Экспедирования (ekspedo), использует абстрактный класс SiriusoBazaAbstrakta3
# (склад konservejo)
class DokumentoEkspedoKonservejoKargo(SiriusoBazaAbstrakta3):

    # LineNumber
    numero = models.IntegerField(_("Numero"), default=None, blank=True, null=True)

    # ТипКонтейнера_Key
    tipo_kontenero = models.ForeignKey(ObjektoTipoKontenero, verbose_name=_("Tipo kontenero"), 
                                       related_name="dokumento_ekspedo_konservejo_kargo_tipo_kontenero",
                                       blank=True, null=True,
                                       default=None, on_delete=models.CASCADE)

    # Длина
    longo = models.FloatField(_("Longo"), default=None, blank=True, null=True)

    # Ширина (larĝo)
    largho = models.FloatField(_("Largho"), default=None, blank=True, null=True)

    # Высота
    alto = models.FloatField(_("Alto"), default=None, blank=True, null=True)

    # КоличествоМест ( (предмет багажа) peco)
    kvanto_pecoj = models.IntegerField(_("Kvanto pecoj"), default=None, blank=True, null=True)

    # Вес
    pezo = models.FloatField(_("Pezo"), default=None, blank=True, null=True)

    # Объем - Температурный режим
    temperatura_reghimo = models.JSONField(verbose_name=_('Temperatura reghimo'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # от какой заявки
    ekspedo = models.ForeignKey(DokumentoEkspedo, verbose_name=_("Ekspedo"), 
                                related_name="dokumento_ekspedo_konservejo_kargo_ekspedo",
                                blank=True, null=True,
                                default=None, on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_ekspedo_konservejo_kargo'
        # читабельное название модели, в единственном числе
        verbose_name = _('Dokumento de ekspedo de konservejo de kargo')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Dokumentoj de ekspedo de konservejo de kargo')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_ekspedo_konservejo_kargo', _('Povas vidi dokumentoj de ekspedo de konservejo de kargo')),
            ('povas_krei_dokumentoj_ekspedo_konservejo_kargo', _('Povas krei dokumentoj de ekspedo de konservejo de kargo')),
            ('povas_forigi_dokumentoj_ekspedo_konservejo_kargo', _('Povas forigi dokumentoj de ekspedo de konservejo de kargo')),
            ('povas_shangxi_dokumentoj_ekspedo_konservejo_kargo', _('Povas ŝanĝi dokumentoj de ekspedo de konservejo de kargo')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}'.format(self.uuid)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_ekspedo_konservejo_kargo', 
                'dokumentoj.povas_krei_dokumentoj_ekspedo_konservejo_kargo',
                'dokumentoj.povas_forigi_dokumentoj_ekspedo_konservejo_kargo',
                'dokumentoj.povas_shangxi_dokumentoj_ekspedo_konservejo_kargo'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        uzanto = user_obj
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_ekspedo_konservejo_kargo')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_ekspedo_konservejo_kargo')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если член организации-владельца (клиента), то выдаём по нему данные
                cond = Q(ekspedo__kliento__organizomembro__uzanto__id=uzanto.id)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_ekspedo_konservejo_kargo'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond


# скл_ГрузыВодитель характеристик документов Экспедирования (ekspedo), использует абстрактный класс SiriusoBazaAbstrakta3
# (склад konservejo) (водитель профессиональный - kondukisto)
class DokumentoEkspedoKonservejoKargoKondukisto(SiriusoBazaAbstrakta3):

    # LineNumber
    numero = models.IntegerField(_("Numero"), default=None, blank=True, null=True)

    # Длина
    longo = models.FloatField(_("Longo"), default=None, blank=True, null=True)

    # Ширина (larĝo)
    largho = models.FloatField(_("Largho"), default=None, blank=True, null=True)

    # Высота
    alto = models.FloatField(_("Alto"), default=None, blank=True, null=True)

    # КоличествоМест ( (предмет багажа) peco)
    kvanto_pecoj = models.IntegerField(_("Kvanto pecoj"), default=None, blank=True, null=True)

    # Вес
    pezo = models.FloatField(_("Pezo"), default=None, blank=True, null=True)

    # Объем - Температурный режим
    temperatura_reghimo = models.JSONField(verbose_name=_('Temperatura reghimo'), blank=True, null=False, default=default_lingvo,
                                  encoder=CallableEncoder)

    # от какой заявки
    ekspedo = models.ForeignKey(DokumentoEkspedo, verbose_name=_("Ekspedo"), 
                                related_name="dokumento_ekspedo_konservejo_kargo_kondukisto_ekspedo",
                                blank=True, null=True,
                                default=None, on_delete=models.CASCADE)

    # дополнительные настройки для модели
    class Meta:
        # название таблицы в базе данных для этой модели
        db_table = 'dokumentoj_ekspedo_konservejo_kargo_kondukisto'
        # читабельное название модели, в единственном числе
        verbose_name = _('Dokumento de ekspedo de konservejo de kargo de kondukisto')
        # читабельное название модели, во множественном числе
        verbose_name_plural = _('Dokumentoj de ekspedo de konservejo de kargo de kondukisto')
        # права
        permissions = (
            ('povas_vidi_dokumentoj_ekspedo_konservejo_kargo_kondukisto', _('Povas vidi dokumentoj de ekspedo de konservejo de kargo de kondukisto')),
            ('povas_krei_dokumentoj_ekspedo_konservejo_kargo_kondukisto', _('Povas krei dokumentoj de ekspedo de konservejo de kargo de kondukisto')),
            ('povas_forigi_dokumentoj_ekspedo_konservejo_kargo_kondukisto', _('Povas forigi dokumentoj de ekspedo de konservejo de kargo de kondukisto')),
            ('povas_shangxi_dokumentoj_ekspedo_konservejo_kargo_kondukisto', _('Povas ŝanĝi dokumentoj de ekspedo de konservejo de kargo de kondukisto')),
        )

    # выбор объекта для отображения в интерфейсах, в том числе администратора
    def __str__(self):
        # для представления объекта будет выведено поле nomo этой модели
        return '{}'.format(self.uuid)

    # Права доступа
    def _get_user_permissions(self, user_obj):
        # Объявляем пустой список прав
        user_perms = Permission.objects.none()

        if user_obj.is_authenticated:
            # Права зарегистриованных для приложения
            all_perms = set(perms.user_registrita_perms(apps=('dokumentoj',)))

            # Преобразуем список прав к имени права без приложения, отфильтровывая только нужные для текущей модели
            # и одно право на создание для дочерней модели
            all_perms = set(perm.split('.')[-1] for perm in all_perms if perm in (
                'dokumentoj.povas_vidi_dokumentoj_ekspedo_konservejo_kargo_kondukisto', 
                'dokumentoj.povas_krei_dokumentoj_ekspedo_konservejo_kargo_kondukisto',
                'dokumentoj.povas_forigi_dokumentoj_ekspedo_konservejo_kargo_kondukisto',
                'dokumentoj.povas_shangxi_dokumentoj_ekspedo_konservejo_kargo_kondukisto'
            ))

            # Делаем выборку прав из модели прав Django
            user_perms = Permission.objects.filter(content_type__app_label='dokumentoj', codename__in=all_perms)

        return user_perms

    def _get_group_permissions(self, user_obj):
        return Permission.objects.none()

    @staticmethod
    def _get_perm_cond(user_obj):
        uzanto = user_obj
        if user_obj.is_authenticated:
            # Для авторизированного пользователя
            if (perms.has_registrita_perm('dokumentoj.povas_vidi_dokumentoj_ekspedo_konservejo_kargo_kondukisto')
                    or user_obj.has_perm('dokumentoj.povas_vidi_dokumentoj_ekspedo_konservejo_kargo_kondukisto')):
                # Если есть право просмотра у зарегистрированного или есть право Django у пользователя
                cond = Q()
            else:
                # Если член организации-владельца (клиента), то выдаём по нему данные
                cond = Q(ekspedo__kliento__organizomembro__uzanto__id=uzanto.id)

        else:
            # Для неавторизированных пользователей
            if perms.has_neregistrita_perm('dokumentoj.povas_vidi_dokumentoj_ekspedo_konservejo_kargo_kondukisto'):
                # Если есть права на просмотр
                cond = Q()
            else:
                # Если права нет, то задаем заведомо невыполнимое условие, например, первичный ключ равен NULL
                cond = Q(uuid__isnull=True)

        return cond

